#ifndef __WIZ_DATATYPE_TREE_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_TREE_HPP__SHANHAOBO_19800429__

#include "../../Base/WizBase.hpp"
#include "./WizDataTypeList.hpp"

namespace Wiz
{
	namespace Tree
	{
		template<class ElementT>
		class Type
        {
            WIZ_DECLARE_CLASS_THIS(Type);
		public:
			Type()
			{}
			Type(const ElementT& D) : m_Data(D)
			{}
			virtual ~Type()
			{
                ::Wiz::List::Type<tThisPtr>::tIterator Itr;
                ::Wiz::List::Type<tThisPtr>::tForEach  FE(Itr, this->m_Children);

                while (FE.HasMoreElement())
                {
                    delete *Itr;
                }

                this->m_Children.Clear();
			}
		public:
			::Wiz::Void::Type Set(const ElementT& D)
			{
				this->m_Data = D;
            }
			ElementT& Get()
			{
				return this->m_Data;
            }
            const ElementT& Get() const
            {
                return this->m_Data;
            }
        public:
		public:
			::Wiz::Bool::Type InsertChild(const ElementT& D)
			{
				tThisPtr newPtr = new tThis(D);
				if (::Wiz::IsValidPtr(newPtr))
				{
					this->m_Children.PushBack(newPtr);
					return ::Wiz::Bool::True;
				}
				return ::Wiz::Bool::False;
            }
            ::Wiz::Bool::Type InsertChild(tThisPtr newPtr)
            {
                WIZ_ASSERT(::Wiz::IsValidPtr(newPtr));
                this->m_Children.PushBack(newPtr);
                return ::Wiz::Bool::True;
            }
			tThisPtr InsertChild()
			{
				tThisPtr newPtr = new tThis();
				if (::Wiz::IsValidPtr(newPtr))
				{
					this->m_Children.PushBack(newPtr);
					return newPtr;
				}
				return WIZ_NULLPTR;
			}
        public:
            /// Deep First
            template<class InsertFunc>
            ::Wiz::Bool::Type InsertDF(const ElementT& D)
            {
                return InsertHelperDF<InsertFunc>(this, D);
            }
        protected:
            template<class InsertFunc>
            ::Wiz::Bool::Type InsertHelperDF(tThisPtr Curr, const ElementT& D)
            {
                WIZ_ASSERT(::Wiz::IsValidPtr(Curr));
                if (InsertFunc(Curr, D))
                {
                    Curr->Set(D);
                    return ::Wiz::Bool::True;
                }
                
                ::Wiz::List::Type<tThisPtr>::tIterator Itr;
                ::Wiz::List::Type<tThisPtr>::tForEach  FE(Itr, Curr->m_Children);

                while (FE.HasMoreElement())
                {
                    if (InsertHelperDF<InsertFunc>(*Itr, D))
                    {
                        return ::Wiz::Bool::True;
                    }
                }

                return ::Wiz::Bool::False;
            }
        public:
            /// Wide First
            template<class InsertFunc>
            ::Wiz::Bool::Type InsertBF(const ElementT& D)
            {
                if (InsertFunc(this, D))
                {
                    this->Set(D);
                    return ::Wiz::Bool::True;
                }
                return InsertHelperBF<InsertFunc>(this->m_Children, D);
            }
        protected:
            template<class InsertFunc>
            ::Wiz::Bool::Type InsertHelperBF(::Wiz::List::Type<tThisPtr>& thisPtrList, const ElementT& D)
            {
                ::Wiz::List::Type<tThisPtr> TempList;

                ::Wiz::List::Type<tThisPtr>::tIterator Itr;
                ::Wiz::List::Type<tThisPtr>::tForEach  FE(Itr, thisPtrList);

                while (FE.HasMoreElement())
                {
                    if (InsertFunc(*Itr, D))
                    {
                        (*Itr)->Set(D);
                        return ::Wiz::Bool::True;
                    }

                    ::Wiz::List::Type<tThisPtr>::tIterator ItrItr;
                    ::Wiz::List::Type<tThisPtr>::tForEach  ItrFE(ItrItr, (*Itr)->m_Children);
                    while (ItrFE.HasMoreElement())
                    {
                        TempList.PushBack(*ItrItr);
                    }
                }

                if (TempList.Size() > 0)
                {
                    return InsertHelperBF<InsertFunc>(TempList, D);
                }

                return ::Wiz::Bool::False;
            }
		protected:
			ElementT									m_Data;
			::Wiz::List::Type<tThisPtr>			        m_Children;
		};
	} /// end of namespace Tree
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_TREE_HPP__SHANHAOBO_19800429__*/
